﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.UI;
using YArchitech.Revit;
using StairsModuleAndEdit.StairsEdit.Common;

namespace StairsModuleAndEdit.StairsEdit.Managers
{
	internal class SearchAllStairs
	{
		public SearchAllStairs(ExternalCommandData DataVal, Stairs stairval)
		{
			this.m_commandData = DataVal;
			this.document = DataVal.Application.ActiveUIDocument.Document;
			this.m_stair = stairval;
			List<Level> list = new List<Level>();
			SearchAllStairs.GetLevelSort(this.document, ref list);
			this.TopLevel = list[(int)list.LongCount<Level>() - 1];
			this.m_BottomElevation = list[0].Elevation;
			this.m_TopElevation = this.TopLevel.Elevation;
		}

		private bool GetAllCurveLoop(ref CurveArrArray arCurves, ref string strMessage)
		{
			Transaction transaction = new Transaction(this.document, "得到所有拉伸体的轮廓线");
			transaction.Start();
			bool result;
			try
			{
				ICollection<ElementId> stairsRuns = this.m_stair.GetStairsRuns();
				foreach (ElementId elementId in stairsRuns)
				{
					StairsRun stairsRun = this.document.GetElement(elementId) as StairsRun;
					CurveLoop curveLoop = stairsRun.GetFootprintBoundary();
					CurveArray curveArray = new CurveArray();
					bool flag = false;
					foreach (Curve curve in curveLoop)
					{
						if (curve is Line)
						{
							Line line = curve as Line;
							XYZ endPoint = line.GetEndPoint(0);
							XYZ xyz = new XYZ(endPoint.X, endPoint.Y, this.m_TopElevation);
							XYZ xyz2 = xyz - endPoint;
							Transform transform = Transform.CreateTranslation(xyz2);
							Line line2 = line.CreateTransformed(transform) as Line;
							curveArray.Append(line2);
						}
						else if (curve is Arc)
						{
							flag = true;
							break;
						}
					}
					if (flag)
					{
						curveLoop = stairsRun.GetStairsPath();
						curveLoop.GetEnumerator().MoveNext();
						IEnumerator<Curve> enumerator3 = curveLoop.GetEnumerator();
						{
							if (enumerator3.MoveNext())
							{
								Curve curve2 = enumerator3.Current;
								Arc arc = curve2 as Arc;
								XYZ center = arc.Center;
								XYZ xyz3 = new XYZ(center.X, center.Y, this.m_TopElevation);
								Arc arc2 = Arc.Create(xyz3, arc.Radius, 0.0, Math.PI, arc.XDirection, arc.YDirection);
								Arc arc3 = Arc.Create(xyz3, arc.Radius, Math.PI, Math.PI*2, arc.XDirection, arc.YDirection);
								curveArray.Append(arc2);
								curveArray.Append(arc3);
							}
						}
					}
					arCurves.Append(curveArray);
				}
				ICollection<ElementId> stairsLandings = this.m_stair.GetStairsLandings();
				foreach (ElementId elementId2 in stairsLandings)
				{
					StairsLanding stairsLanding = this.document.GetElement(elementId2) as StairsLanding;
					CurveLoop footprintBoundary = stairsLanding.GetFootprintBoundary();
					CurveArray curveArray2 = new CurveArray();
					foreach (Curve curve3 in footprintBoundary)
					{
						if (curve3 is Line)
						{
							Line line3 = curve3 as Line;
							XYZ endPoint2 = line3.GetEndPoint(0);
							XYZ xyz4 = new XYZ(endPoint2.X, endPoint2.Y, this.m_TopElevation);
							XYZ xyz5 = xyz4 - endPoint2;
							Transform transform2 = Transform.CreateTranslation(xyz5);
							Line line4 = line3.CreateTransformed(transform2) as Line;
							curveArray2.Append(line4);
						}
						else if (curve3 is Arc)
						{
							Arc arc4 = curve3 as Arc;
							XYZ center2 = arc4.Center;
							XYZ xyz6 = new XYZ(center2.X, center2.Y, this.m_TopElevation);
							XYZ xyz7 = xyz6 - center2;
							Transform transform3 = Transform.CreateTranslation(xyz7);
							Arc arc5 = arc4.CreateTransformed(transform3) as Arc;
							curveArray2.Append(arc5);
						}
					}
					arCurves.Append(curveArray2);
				}
				transaction.Commit();
				result = true;
			}
			catch (Exception ex)
			{
				strMessage = ex.Message;
				transaction.RollBack();
				result = false;
			}
			return result;
		}

		public bool GetAllIntersectionStairs(ref List<Element> RefStairs, ref string strMessage)
		{
			if (this.m_stair == null)
			{
				return false;
			}
			CurveArrArray curveArrArray = new CurveArrArray();
			if (!this.GetAllCurveLoop(ref curveArrArray, ref strMessage))
			{
				return false;
			}
			FloorType floorType = null;
			bool floorType2 = this.GetFloorType(ref floorType, ref strMessage);
			if (!floorType2 || floorType == null)
			{
				return false;
			}
			Transaction transaction = new Transaction(this.document, "创建楼板");
			transaction.Start();
			try
			{
				foreach (object obj in curveArrArray)
				{
					CurveArray curveArray = (CurveArray)obj;
					Floor floor = this.document.Create.NewFloor(curveArray, floorType, this.TopLevel, false, new XYZ(0.0, 0.0, 1.0));
					floor.GetParameter(BuiltInParameter.FLOOR_HEIGHTABOVELEVEL_PARAM).Set(2000.0 / CommonUnit.MM2Feet);
					this.document.Regenerate();
					if (!this.getInsectionElementByDoc(ref RefStairs, floor, ref strMessage))
					{
						transaction.RollBack();
						return false;
					}
					this.document.Delete(floor.Id);
				}
				transaction.Commit();
			}
			catch (Exception ex)
			{
				strMessage = ex.Message;
				transaction.RollBack();
				return false;
			}
			return true;
		}

		public bool GetFloorType(ref FloorType SelFloorType, ref string strMessage)
		{
			double num = 2000.0 / CommonUnit.MM2Feet;
			double num2 = this.m_TopElevation - this.m_BottomElevation;
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.document);
			IList<Element> list = filteredElementCollector.OfClass(typeof(FloorType)).WhereElementIsElementType().ToElements();
			SelFloorType = null;
			foreach (Element element in list)
			{
				FloorType floorType = element as FloorType;
				double num3 = floorType.GetParameter(BuiltInParameter.FLOOR_ATTR_DEFAULT_THICKNESS_PARAM).AsDouble();
				if (num3 > num2)
				{
					SelFloorType = floorType;
					return true;
				}
			}
			for (int i = list.Count - 1; i >= 0; i--)
			{
				FloorType floorType2 = list[i] as FloorType;
				if (floorType2.IsFoundationSlab)
				{
					list.RemoveAt(i);
				}
			}
			Transaction transaction = new Transaction(this.document, "创建楼板类型");
			transaction.Start();
			try
			{
				string text = "用作查找所有楼梯";
				int num4 = 0;
				foreach (Element element2 in list)
				{
					if (element2.Name.Equals(text))
					{
						num4++;
					}
				}
				if (num4 > 0)
				{
					text += num4.ToString();
				}
				SelFloorType = ((list[0] as FloorType).Duplicate(text) as FloorType);
				double num3 = SelFloorType.GetParameter(BuiltInParameter.FLOOR_ATTR_DEFAULT_THICKNESS_PARAM).AsDouble();
				num = num + num2 - num3;
				CompoundStructure compoundStructure = SelFloorType.GetCompoundStructure();
				IList<CompoundStructureLayer> layers = compoundStructure.GetLayers();
				layers.Add(new CompoundStructureLayer
				{
					Width = num,
                    Function = (MaterialFunctionAssignment)4
				});
				compoundStructure.SetLayers(layers);
				SelFloorType.SetCompoundStructure(compoundStructure);
				transaction.Commit();
			}
			catch (Exception ex)
			{
				strMessage = ex.Message;
				transaction.RollBack();
				return false;
			}
			return true;
		}

		public bool getInsectionElementByDoc(ref List<Element> elements, Floor floor, ref string strMessage)
		{
			IList<Solid> list = new List<Solid>();
			this.GetFloorGeo(ref list, floor);
			if (list.LongCount<Solid>() == 0L)
			{
				strMessage = "计算相交时，拉伸体获取失败。";
				return false;
			}
			Solid solid = list[0];
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.document);
			ElementIntersectsSolidFilter elementIntersectsSolidFilter = new ElementIntersectsSolidFilter(solid);
			IList<Element> list2 = filteredElementCollector.WherePasses(elementIntersectsSolidFilter).OfClass(typeof(Stairs)).ToElements();
			IEnumerator<Element> enumerator = list2.GetEnumerator();
			{
				while (enumerator.MoveNext())
				{
					Element e = enumerator.Current;
					if (elements.Find((Element p) => p.Id == e.Id) == null)
					{
						elements.Add(e);
					}
				}
			}
			return true;
		}

		private Result GetFloorGeo(ref IList<Solid> Solids, Floor floor)
		{
			GeometryElement elem = floor.get_Geometry(new Options
			{
				ComputeReferences = true,
				IncludeNonVisibleObjects = true,
				View = this.document.ActiveView
			});
			return this.GetElemGeo(elem, ref Solids);
		}

		private Result GetElemGeo(GeometryElement elem, ref IList<Solid> Solids)
		{
			foreach (GeometryObject geometryObject in elem)
			{
				if (geometryObject is Solid)
				{
					Solid item = geometryObject as Solid;
					Solids.Add(item);
				}
				else if (geometryObject is GeometryInstance)
				{
					GeometryInstance geometryInstance = geometryObject as GeometryInstance;
					GeometryElement symbolGeometry = geometryInstance.GetSymbolGeometry();
					Result elemGeo = this.GetElemGeo(symbolGeometry, ref Solids);
					if (elemGeo != null)
					{
						return elemGeo;
					}
				}
			}
			return Autodesk.Revit.UI.Result.Succeeded;
		}

		public static void GetLevelSort(Autodesk.Revit.DB.Document doc, ref List<Level> LevelSort)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			IList<Element> list = new List<Element>();
			filteredElementCollector.OfCategory(BuiltInCategory.OST_Levels);
			filteredElementCollector.WhereElementIsNotElementType();
			list = filteredElementCollector.ToElements();
			foreach (Element element in list)
			{
				LevelSort.Add(element as Level);
			}
			for (int i = 0; i < list.Count - 1; i++)
			{
				for (int j = i + 1; j < list.Count; j++)
				{
					Level value = LevelSort[i];
					double elevation = LevelSort[i].Elevation;
					double elevation2 = LevelSort[j].Elevation;
					if (elevation > elevation2)
					{
						value = LevelSort[i];
						LevelSort[i] = LevelSort[j];
						LevelSort[j] = value;
					}
				}
			}
		}

		private ExternalCommandData m_commandData;

		private Document document;

		private Stairs m_stair;

		private Level TopLevel;

		private double m_BottomElevation;

		private double m_TopElevation;
	}
}
